using System;
using System.Diagnostics;
using System.Text;
using System.Security.Principal;
using System.Reflection;
using System.Configuration;

using KodeIT.Web.Properties;
using KodeIT.Web.Configuration;
using System.IO;

namespace KodeIT.Web
{
    internal static class ErrorPage
    {
        private static string GetErrorWithDetails()
        {
            return Resources.errorWithDetails;
        }

        private static string GetErrorWithoutDetails(HttpFiltersSection filtersSection)
        {
            if (String.IsNullOrEmpty(filtersSection.ErrorPage))
            {
                return Resources.errorWithoutDetails;
            }

            try
            {
                Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
                return File.ReadAllText(filtersSection.ErrorPage);
            }
            catch (Exception exp)
            {
                EventHelper.Write(String.Format(
                    "Unable to read from the custom error page located at '{0}'", filtersSection.ErrorPage), exp);
                return Resources.errorWithoutDetails;
            }
        }

        private static string GetErrorPage(ContextEvent context)
        {
            HttpFiltersSection filtersSection = ConfigurationManager.GetSection("httpFilters") as HttpFiltersSection;
            
            if (filtersSection.ErrorDetail == ErrorDetail.On)
            {
                return GetErrorWithDetails();
            }
            else if (filtersSection.ErrorDetail == ErrorDetail.Off)
            {
                return GetErrorWithoutDetails(filtersSection);
            }
            else if (filtersSection.ErrorDetail == ErrorDetail.LocalOnly)
            {
                try
                {
                    if (context.IsLocal)
                    {
                        return GetErrorWithDetails();
                    }
                }
                catch(Exception exp)
                {
                    EventHelper.Write(
                        "Unable to determine if the current request is local", exp);
                }
            }

            return GetErrorWithoutDetails(filtersSection);
        }

        internal static string GetPayload(ContextEvent context, FilterEvent filterEvent, Type type, Exception exp)
        {
            string exceptionInfo = String.Format("{0}: {1}",
                exp.GetType().Name,
                exp.Message);

            Process process = Process.GetCurrentProcess();

            StringBuilder sb = new StringBuilder(GetErrorPage(context));
            sb = sb.Replace("$title", exp.Message);
            sb = sb.Replace("$scope", "Filter Processing Error");
            sb = sb.Replace("$event", Enum.GetName(filterEvent.GetType(), filterEvent));
            sb = sb.Replace("$instance", null != type ? type.AssemblyQualifiedName : String.Empty);
            sb = sb.Replace("$processId", process.Id.ToString());
            sb = sb.Replace("$processName", process.ProcessName + ".exe");
            sb = sb.Replace("$processAccount", WindowsIdentity.GetCurrent().Name);
            sb = sb.Replace("$exception", exceptionInfo);
            sb = sb.Replace("$stack", exp.StackTrace);
            sb = sb.Replace("$filterversion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
            sb = sb.Replace("$clrversion", Assembly.GetExecutingAssembly().ImageRuntimeVersion);

            return sb.ToString();
        }

        internal static string GetPayload(ContextEvent context, FilterEvent filterEvent, Exception exp)
        {
            return GetPayload(context, filterEvent, null, exp);
        }
    }
}
